home *** CD-ROM | disk | FTP | other *** search
- /*
- * SFskyedit - Star Fighter 3000 sky colours editor
- * Sky preview window
- * Copyright (C) 2001 Chris Bazley
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public Licence as published by
- * the Free Software Foundation; either version 2 of the Licence, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public Licence for more details.
- *
- * You should have received a copy of the GNU General Public Licence
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
- #include "Preview.h"
-
- /* ANSI library files */
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
-
- /* RISC OS library files */
- #include "kernel.h"
- #include "swis.h"
- #include "wimp.h"
- #include "toolbox.h"
- #include "event.h"
- #include "wimplib.h"
- #include "window.h"
- #include "menu.h"
- #include "flex.h"
-
- /* My library files */
- #include "err.h"
- #include "msgtrans.h"
- #include "Macros.h"
- #include "SFformats.h"
- #include "SprFormats.h"
- #include "NoBudge.h"
-
- /* Local headers */
- #include "Utils.h"
- #include "EditSky.h"
- #include "Render.h"
- #include "Preview.h"
- #include "Main.h"
-
- /* Gadgets */
- #define PREVIEW_SLIDER 0x00
- #define PREVIEW_NUMDISP 0x01
-
- #define PREVIEW_MENU_MINSKY 0x00
- #define PREVIEW_MENU_STARS 0x01
-
- /* Key shortcuts */
- #define KEY_SET_SKYHEIGHT 0x0a
- #define KEY_SET_STARHEIGHT 0x0b
- #define KEY_UP 0x0c
- #define KEY_DOWN 0x0d
- #define KEY_ESCAPE 0x0e
-
- typedef struct _PreviewData
- {
- ObjectId heightslider;
- ObjectId prevmenu;
- int render_height;
- bool have_caret;
- spriteareaheader *cached_image;
- } PreviewData;
-
- /* ----------------------------------------------------------------------- */
- /* Function prototypes */
-
- static ToolboxEventHandler _Preview_sliderhandler, _Preview_deletedhandler, _Preview_openhandler, _Preview_menuhandler, _Preview_keyhandler;
-
- static WimpEventHandler _Preview_redrawhandler;
-
- static void _Preview_setheight(PreviewData *preview_data, int height);
-
- /* ----------------------------------------------------------------------- */
- /* Public functions */
-
- ObjectId Preview_create(void)
- {
- PreviewData *preview_data;
- ObjectId window_id;
- _kernel_swi_regs regs;
-
- /* Create data block for this window */
- preview_data = malloc(sizeof(PreviewData));
- if(preview_data == NULL)
- MG_RETV("NoMem", NULL_ObjectId); /* failed */
- preview_data->have_caret = false;
-
- /* Create sprite area to cache sky image */
- if(!flex_alloc((flex_ptr)&preview_data->cached_image, sizeof(spriteareaheader) + sizeof(spriteheader) + (320*256))) {
- MG("NoMem");
- goto err_exit1; /* no room */
- }
-
- preview_data->cached_image->size = sizeof(spriteareaheader) + sizeof(spriteheader) + (320*256);
- preview_data->cached_image->first = sizeof(spriteareaheader);
- regs.r[0] = SPRITEOP_INIT_AREA + SPRITEOP_USERAREA_SPRNAME;
- regs.r[1] = (int)preview_data->cached_image;
- if(E(_kernel_swi(OS_SpriteOp, ®s, ®s)))
- goto err_exit2;
-
- regs.r[0] = SPRITEOP_CREATE + SPRITEOP_USERAREA_SPRNAME;
- regs.r[1] = (int)preview_data->cached_image;
- regs.r[2] = (int)"Cache";
- regs.r[3] = 0; /* no palette */
- regs.r[4] = 320;
- regs.r[5] = 256;
- regs.r[6] = 13; /* mode number */
- if(E(_kernel_swi(OS_SpriteOp, ®s, ®s)))
- goto err_exit2;
-
- /* Create Window object */
- if(E(toolbox_create_object(0, "Preview", &window_id)))
- goto err_exit2;
- if(E(toolbox_set_client_handle(0, window_id, preview_data)))
- goto err_exit3;
-
- /* Get IDs of attached objects */
- if(E(window_get_tool_bars(Window_ExternalTopLeftToolbar, window_id, NULL, NULL, NULL, &preview_data->heightslider)))
- goto err_exit3;
- if(E(window_get_menu(0, window_id, &preview_data->prevmenu)))
- goto err_exit3;
-
- /* Register event handlers
- Note that ObjectDeleted handler is registered AFTER anything that could cause an error and therefore premature deletion!
- */
- if(!E(event_register_wimp_handler(window_id, Wimp_ERedrawWindow, _Preview_redrawhandler, preview_data))
- && !E(event_register_toolbox_handler(preview_data->prevmenu, Menu_Selection, _Preview_menuhandler, preview_data))
- && !E(event_register_toolbox_handler(preview_data->heightslider, Slider_ValueChanged, _Preview_sliderhandler, preview_data))
- && !E(event_register_toolbox_handler(window_id, Window_AboutToBeShown, _Preview_openhandler, preview_data))
- && !E(event_register_toolbox_handler(window_id, Window_HasBeenHidden, hand_back_caret, &preview_data->have_caret))
- && !E(event_register_wimp_handler(window_id, -1, watch_caret, &preview_data->have_caret))
- && !E(event_register_toolbox_handler(window_id, -1, _Preview_keyhandler, preview_data))
- && !E(event_register_toolbox_handler(window_id, Toolbox_ObjectDeleted, _Preview_deletedhandler, preview_data)))
- return window_id; /* success */
-
- err_exit3:
- toolbox_delete_object(0, window_id);
- err_exit2:
- flex_free((flex_ptr)&preview_data->cached_image);
- err_exit1:
- free(preview_data);
- return NULL_ObjectId; /* failed */
- }
-
- /* -------------------------------------------------------------------------- */
-
- void Preview_rendersky(ObjectId objectref)
- {
- BBox redraw_box;
- spriteheader *first_spr;
- ObjectId editwin;
- PreviewData *preview_data;
- ViewData *view_data;
-
- /* Get data associated with preview and editing windows */
- E_RET(toolbox_get_client_handle(0, objectref, (void **)&preview_data));
-
- E_RET(toolbox_get_ancestor(0, objectref, &editwin, NULL));
- E_RET(toolbox_get_client_handle(0, editwin, (void **)&view_data));
-
- /* Render sky to image cache at current height */
- nobudge_register(32);
- first_spr = (spriteheader *)((int)preview_data->cached_image + preview_data->cached_image->first);
- sky_drawsky(preview_data->render_height, &view_data->sky, (void *)((int)first_spr + first_spr->image), (256*320)-4);
- nobudge_deregister();
-
- /* Force redraw of window */
- if(!E(window_get_extent(0, objectref, &redraw_box))) {
- RE(window_force_redraw(0, objectref, &redraw_box));
- }
- }
-
- /* ----------------------------------------------------------------------- */
- /* Private handlers */
-
- static int _Preview_openhandler(int event_code, ToolboxEvent *event, IdBlock *id_block, void *handle)
- {
- /* Start at ground level */
- _Preview_setheight((PreviewData *)handle, 0);
-
- /* Render sky preview */
- Preview_rendersky(id_block->self_id);
- return 1; /* claim event */
- }
-
- /* ----------------------------------------------------------------------- */
-
- static int _Preview_deletedhandler(int event_code, ToolboxEvent *event, IdBlock *id_block, void *handle)
- {
- PreviewData *preview_data = (PreviewData *)handle;
-
- /* Remove handlers */
- RE(event_deregister_toolbox_handler(preview_data->heightslider, Slider_ValueChanged, _Preview_sliderhandler, handle));
- RE(event_deregister_toolbox_handler(id_block->self_id, Toolbox_ObjectDeleted, _Preview_deletedhandler, handle));
- RE(event_deregister_toolbox_handler(id_block->self_id, Window_AboutToBeShown, _Preview_openhandler, handle));
- RE(event_deregister_wimp_handler(id_block->self_id, Wimp_ERedrawWindow, _Preview_redrawhandler, handle));
- RE(event_deregister_toolbox_handler(id_block->self_id, -1, _Preview_keyhandler, handle));
- RE(event_deregister_toolbox_handler(preview_data->prevmenu, Menu_Selection, _Preview_menuhandler, handle));
- RE(event_deregister_toolbox_handler(id_block->self_id, Window_HasBeenHidden, hand_back_caret, NULL));
-
- /* Free image cache */
- flex_free((flex_ptr)&preview_data->cached_image);
- /* Free preview data block */
- free(preview_data);
- return 1; /* claim event */
- }
-
- /* -------------------------------------------------------------------------- */
-
- static int _Preview_keyhandler(int event_code, ToolboxEvent *event, IdBlock *id_block, void *handle)
- {
- PreviewData *preview_data = (PreviewData *)handle;
- int temp_renderheight;
-
- /* Handle hotkey events */
- switch(event_code) {
-
- case KEY_SET_SKYHEIGHT: /* Ctrl-M Set minimum sky rendering height */
- /* Shift viewing height to new ground 0 (so it looks the same) */
- temp_renderheight = preview_data->render_height;
- _Preview_setheight(preview_data, 0);
-
- /* Tell edit window to set minimum sky height and redraw */
- EditSky_set_minheight(id_block->ancestor_id, temp_renderheight);
- return 1; /* claim event */
-
- case KEY_SET_STARHEIGHT:
- /* Ctrl-S Set height to start plotting stars */
- EditSky_set_starheight(id_block->ancestor_id, preview_data->render_height);
- return 1; /* claim event */
-
- case KEY_UP:
- /* Up - increase viewing height */
- if(preview_data->render_height >= 2250)
- return 1; /* claim event */
- _Preview_setheight(preview_data, preview_data->render_height+10);
- Preview_rendersky(id_block->self_id);
- return 1; /* claim event */
-
- case KEY_DOWN:
- /* Down - decrease viewing height */
- if(preview_data->render_height <= 0)
- return 1; /* claim event */
- _Preview_setheight(preview_data, preview_data->render_height-10);
- Preview_rendersky(id_block->self_id);
- return 1; /* claim event */
-
- case KEY_ESCAPE:
- /* ESC - Close preview */
- RE(toolbox_hide_object(0, id_block->self_id));
- /* N.B. Don't need to worry about the window being iconised
- since iconised windows get no keypresses */
- return 1; /* claim event */
- }
- return 0; /* Not an event that we handle */
- }
-
- /* -------------------------------------------------------------------------- */
-
- static int _Preview_menuhandler(int event_code, ToolboxEvent *event, IdBlock *id_block, void *handle)
- {
- PreviewData *preview_data = (PreviewData *)handle;
- int temp_renderheight;
-
- /* Handle menu selections */
- switch(id_block->self_component) {
- case PREVIEW_MENU_MINSKY:
- /* Shift viewing height to new ground 0 (i.e. same!) */
- temp_renderheight = preview_data->render_height;
- _Preview_setheight(preview_data, 0);
- /* Tell edit window to set minimum sky height and redraw */
- EditSky_set_minheight(id_block->ancestor_id, temp_renderheight);
- return 1; /* claim event */
-
- case PREVIEW_MENU_STARS:
- /* Set height to start plotting stars */
- EditSky_set_starheight(id_block->ancestor_id, preview_data->render_height);
- return 1; /* claim event */
- }
- return 0; /* event not handled */
- }
-
- /* -------------------------------------------------------------------------- */
-
- static int _Preview_sliderhandler(int event_code, ToolboxEvent *event, IdBlock *id_block, void *handle)
- {
- PreviewData *preview_data = (PreviewData *)handle;
-
- if(id_block->self_component != PREVIEW_SLIDER
- || ((SliderValueChangedEvent *)event)->new_value == preview_data->render_height)
- return 0; /* Wrong component or no change in value */
-
- /* Set viewing height for sky render */
- preview_data->render_height = ((SliderValueChangedEvent *)event)->new_value;
- RE(numberrange_set_value(0, id_block->self_id, PREVIEW_NUMDISP, preview_data->render_height));
- Preview_rendersky(id_block->parent_id);
- return 1; /* claim event */
- }
-
- /* ----------------------------------------------------------------------- */
-
- static int _Preview_redrawhandler(int event_code, WimpPollBlock *event, IdBlock *id_block, void *handle)
- {
- /* Custom redraw from cached sky image */
- PreviewData *preview_data = (PreviewData *)handle;
- WimpRedrawWindowBlock block;
- int more, botleft_x, botleft_y;
- _kernel_swi_regs regs;
-
- nobudge_register(1024);
- block.window_handle = ((WimpRedrawWindowRequestEvent)event->redraw_window_request).window_handle;
- E_RETV(wimp_redraw_window(&block, &more), 1);
- botleft_x = block.visible_area.xmin - block.xscroll;
- botleft_y = block.visible_area.ymax - block.yscroll - 512; /* get origin */
-
- while (more) {
- regs.r[0] = SPRITEOP_PLOTSCALED + SPRITEOP_USERAREA_SPRPTR;
- regs.r[1] = (int)preview_data->cached_image; /* sprite area */
- regs.r[2] = (int)preview_data->cached_image + preview_data->cached_image->first; /* sprite pointer */
- regs.r[3] = botleft_x; /* X coordinate */
- regs.r[4] = botleft_y; /* Y coordinate */
- regs.r[5] = 0; /* plot action */
- regs.r[6] = (int)scale_factors; /* scale factors */
- regs.r[7] = (int)transtable;
- RE(_kernel_swi(OS_SpriteOp, ®s, ®s));
- E_RETV(wimp_get_rectangle(&block, &more), 1);
- }
- nobudge_deregister();
-
- return 1; /* claim event */
- }
-
- /* ----------------------------------------------------------------------- */
- /* Private functions */
-
- static void _Preview_setheight(PreviewData *preview_data, int height)
- {
- /* Set viewing height and attached slider/numeric display */
-
- RE(slider_set_value(0, preview_data->heightslider, PREVIEW_SLIDER, height));
- RE(numberrange_set_value(0, preview_data->heightslider, PREVIEW_NUMDISP, height));
- preview_data->render_height = height;
- }
-